<?php
    namespace Util;
    

    class FastDFSClient{
        private $fdfs,$tracker,$storage;
        public function __construct(){
            $this->fdfs = new \FastDFS();

            //获取tracker的连接
            $this->tracker = $this->fdfs->tracker_get_connection();
            if(!$this->tracker) {
                throw new \Exception('cannot connect to tracker server:[' .
                    $this->fdfs->get_last_error_no().']' .
                    $this->fdfs->get_last_error_info());
            }

            //获取存储服务的信息并且获取连接
            $this->storage = $this->fdfs->tracker_query_storage_store();
            $this->server = $this->fdfs->connect_server(
                $this->storage['ip_addr'], $this->storage['port']
            );
            if(!$this->server){
                throw new \Exception('cannot connect to storage server' .
                    $this->storage['ip_addr'] . ':' .
                    $this->storage['port'] . ':[' .
                    $this->fdfs->get_last_error_no().']' .
                    $this->fdfs->get_last_error_info());
            }

            $this->storage['sock'] = $this->server['sock'];
            
        }

        /**
         * 上传文件
         * @param $localFile 本地要上传的文件
         * @param 文件的扩展名
         * @return mix 成功返回数组信息，失败返回false
         */
        public function upload($localFile,$ext_name){
            $info = $this->fdfs->storage_upload_by_filename($localFile,$ext_name);

            if(is_array($info)){
                $group_name = $info['group_name'];
                $remote_filename = $info['filename'];
                $source_info = $this->fdfs->get_file_info($group_name,$remote_filename);
                
                $source_ip = $source_info['source_ip_addr'];
                $file_size = $source_info['file_size'];
                return compact('group_name','remote_filename','source_ip','file_size');
            }

            return false;
        }

        /**
         * 使用二进制流上传文件
         * @param $blob 二进制流
         * @param $ext_name 扩展名
         * @return mix 成功返回数组信息，失败返回false
         */
        public function uploadBlob($blob,$ext_name){
            $info = $this->fdfs->storage_upload_by_filebuff($blob,$ext_name);
            if(is_array($info)){
                $group_name = $info['group_name'];
                $remote_filename = $info['filename'];
                $source_info = $this->fdfs->get_file_info($group_name,$remote_filename);
                
                $source_ip = $source_info['source_ip_addr'];
                $file_size = $source_info['file_size'];
                return compact('group_name','remote_filename','source_ip','file_size');
            }

            return false;
        }

        /**
         * 下载文件到内存中
         * @param $group_name 文件所在的组名（卷名）
         * @param $remote_filename 远程存储的文件名
         * @return bytes 内存buffer
         */
        public function download_to_buff($group_name,$remote_filename){
            $content = $this->fdfs->storage_download_file_to_buff($group_name,$remote_filename);

            return $content;
        }

        /** 
         * 下载文件到本地文件中
         * @param $group_name 文件所在的组名（卷名)
         * @param $remote_filename  远程存储的文件名
         * @param $dst_localfile  下载到的文件名
         * @return boolean 下载成功返回true,失败返回false
         */
        public function download_to_file($group_name,$remote_filename,$dst_localfile){
            return $this->fdfs->storage_download_file_to_file($group_name,$remote_filename,$dst_localfile);
        }

        /**
         * 删除文件
         * @param $group_name 文件所在的组名（卷名)
         * @param $remote_filename 远程存储的文件名
         * @return boolean 下载成功返回true，失败返回false
         */
        public function delete($group_name,$remote_filename){
            return $this->fdfs->storage_delete_file($group_name,$remote_filename);
        }

        /**
         * 检查文件是否存在
         * @param $group_name 文件所在的组名（卷名)
         * @param $remote_filename 远程存储的文件名
         * @return boolean 存在返回true,失败返回false
         */
        public function exists($group_name,$remote_filename){
            return $this->fdfs->storage_file_exist($group_name,$remote_filename);
        }

        /**
         * 获取文件信息
         * @param $group_name 文件所在的组名（卷名)
         * @param $remote_filename 远程存储的文件名
         * @return mix 成功时返回文件信息数组，失败时返回false
         */
        public function get_file_info($group_name,$remote_filename){
            return $this->fdfs->get_file_info($group_name,$remote_filename);
        }

        /**
         * 获取最后一个错误信息
         * @return string 错误信息
         */
        public function get_last_error_info(){
            return $this->fdfs->get_last_error_info();
        }   
    }